function [ FS,E ] = GA( FS,E,Tg,pc,train_t_input,train_v_input,train_t_target,train_v_target, algorithm0)
%GA Generic Algorithm
%   Detailed explanation goes here

%  FS:Feature subset
%  Tk:The total time for GA
%  train_t_input��training dataset
%  train_v_input:Validation dataset
%  train_t_target:Training label 
%  train_v_target:Validation label


u_target = train_t_target;     
v_target = train_v_target;      
while Tg>0
    tic
    R = size(FS,1);              
    %     %Unbiased Tournament Selection
    %     P = [];
    %     I = [];
    %     i = 1;
    %     while i < R+1
    %         x = fix(rand(1)*R+1);
    %         if (x ~= i)
    %             [ yes ] = IfAdded( P,x );
    %             if yes=='N'
    %                 P(i) = x;
    %                 i = i+1;
    %             end;
    %         end;
    %     end;
    %
    %     for i=1:R
    %         if E(i)<E(P(i))
    %             I(i) = P(i);
    %         else
    %             I(i) = i;
    %         end;
    %     end;
    %     U = [];               
    %     for i=1:R
    %         U(i,:) = FS(I(i),:);
    %     end;
    %
    %     FS = U;              

    %The code above is Unbiased tournament selection
    %The code below is linear roulette selection
    P = E/sum(E);
    num = 100;
    Select = Roulette(P,num);
    U = [];
    for i=1:100
        U(i,:) = FS(Select(i),:);
    end

    FS = U;

    %crossover
    [FS] = crossover(FS,pc);   
    %muatation
    [FS] = mutation(FS,0.001);  
    toc
    Tspent = toc;
    Tg = Tg-Tspent;

    %Evaluate the fitness
    for i=1:length(E)
        if Tg>0
            t1 = clock;
            feasub = FS(i,:);                     
            din = find(feasub);                   
            u = train_t_input(:,din);             
            v = train_v_input(:,din);            

            %Evaluate the fitness of the offspring
            %Average_Precision as the Fitness function
            %         [Prior,PriorN,Cond,CondN]=MLKNN_train(u,u_target',10,1);
            %         [HammingLoss_fs,RankingLoss_fs,OneError_fs,Coverage_fs,Average_Precision_fs,Outputs_fs,Pre_Labels_fs]=MLKNN_test(u,u_target',v,v_target',10,Prior,PriorN,Cond,CondN);
            %Update the fitness
            
%             [Prior,PriorN,Cond,CondN]=MLKNN_train(u,u_target',10,1);
%             [HammingLoss,RankingLoss,OneError,Coverage,Average_Precision,Outputs,Pre_Labels]=MLKNN_test(u,u_target',v,v_target',10,Prior,PriorN,Cond,CondN);
%             E(i) = Average_Precision;
            algorithm0.build(u, u_target);
            result_i = algorithm0.apply(u, u_target);
            E(i) = AveragePrecision.calc(u_target, result_i.Y_hat);
            
            t2 = clock;
            Tspent = etime(t2,t1) ;
            Tg = Tg-Tspent;
        else
            break
        end%if

    end%for
end%while

end
